//
// DotNetNuke - http://www.dotnetnuke.com
// Copyright (c) 2002-2010
// by Perpetual Motion Interactive Systems Inc. ( http://www.perpetualmotion.ca )
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation 
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and 
// to permit persons to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions 
// of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
// DEALINGS IN THE SOFTWARE.
//

using System;
using System.Collections.Generic;
using System.Data.Common;
using System.IO;
using System.Xml.XPath;
using DotNetNuke.Common.Utilities;
using DotNetNuke.Data;
namespace DotNetNuke.Services.Installer.Installers
{
	public class ScriptInstaller : FileInstaller
	{
		private InstallFile _InstallScript;
		private SortedList<System.Version, InstallFile> _InstallScripts = new SortedList<System.Version, InstallFile>();
		private DbTransaction _Transaction;
		private SortedList<System.Version, InstallFile> _UnInstallScripts = new SortedList<System.Version, InstallFile>();
		private InstallFile _UpgradeScript;
		protected InstallFile InstallScript
		{
			get { return _InstallScript; }
		}
		protected SortedList<System.Version, InstallFile> InstallScripts
		{
			get { return _InstallScripts; }
		}
		protected SortedList<System.Version, InstallFile> UnInstallScripts
		{
			get { return _UnInstallScripts; }
		}
		protected override string CollectionNodeName
		{
			get { return "scripts"; }
		}
		protected override string ItemNodeName
		{
			get { return "script"; }
		}
		protected Framework.Providers.ProviderConfiguration ProviderConfiguration
		{
			get { return Framework.Providers.ProviderConfiguration.GetProviderConfiguration("data"); }
		}
		protected InstallFile UpgradeScript
		{
			get { return _UpgradeScript; }
		}
		public override string AllowableFiles
		{
			get { return "*dataprovider, sql"; }
		}
		private bool ExecuteSql(InstallFile scriptFile, bool useTransaction)
		{
			bool bSuccess = true;
			Log.AddInfo(string.Format(Util.SQL_BeginFile, scriptFile.Name));
			string strScript = FileSystemUtils.ReadFile(PhysicalBasePath + scriptFile.FullName);
			if (strScript.StartsWith("?"))
			{
				strScript = strScript.Substring(1);
			}
			string strSQLExceptions = Null.NullString;
			strSQLExceptions = DataProvider.Instance().ExecuteScript(strScript);
			if (!String.IsNullOrEmpty(strSQLExceptions))
			{
				if (Package.InstallerInfo.IsLegacyMode)
				{
					Log.AddWarning(string.Format(Util.SQL_Exceptions, Environment.NewLine, strSQLExceptions));
				}
				else
				{
					Log.AddFailure(string.Format(Util.SQL_Exceptions, Environment.NewLine, strSQLExceptions));
					bSuccess = false;
				}
			}
			Log.AddInfo(string.Format(Util.SQL_EndFile, scriptFile.Name));
			return bSuccess;
		}
		private bool InstallScriptFile(InstallFile scriptFile)
		{
			//Call base InstallFile method to copy file
			bool bSuccess = InstallFile(scriptFile);
			string fileExtension = Path.GetExtension(scriptFile.Name.ToLower()).Substring(1);

			//Process the file if it is an Install Script
			if (bSuccess && (ProviderConfiguration.DefaultProvider.ToLower() == fileExtension || AllowableFiles.Contains(fileExtension)))
			{
				Log.AddInfo(Util.SQL_Executing + scriptFile.Name);
				//bSuccess = ExecuteSql(scriptFile, True)
				bSuccess = ExecuteSql(scriptFile, false);
			}

			return bSuccess;
		}
		protected override bool IsCorrectType(InstallFileType type)
		{
			return (type == InstallFileType.Script);
		}
		protected override void ProcessFile(InstallFile file, XPathNavigator nav)
		{
			string type = nav.GetAttribute("type", "");
			if (file != null && IsCorrectType(file.Type))
			{
				if (file.Name.ToLower().StartsWith("install."))
				{
					_InstallScript = file;
				}
				else if (file.Name.ToLower().StartsWith("upgrade."))
				{
					_UpgradeScript = file;
				}
				else if (type.ToLower() == "install")
				{
					InstallScripts[file.Version] = file;
				}
				else
				{
					UnInstallScripts[file.Version] = file;
				}
			}
			base.ProcessFile(file, nav);
		}
		protected override void UnInstallFile(InstallFile scriptFile)
		{
			if (UnInstallScripts.ContainsValue(scriptFile) && ProviderConfiguration.DefaultProvider.ToLower() == Path.GetExtension(scriptFile.Name.ToLower()).Substring(1))
			{
				if (scriptFile.Name.ToLower().StartsWith("uninstall."))
				{
					Log.AddInfo(Util.SQL_Executing + scriptFile.Name);
					ExecuteSql(scriptFile, false);
				}
			}
			base.UnInstallFile(scriptFile);
		}
		public override void Commit()
		{
			base.Commit();
		}
		public override void Install()
		{
			Log.AddInfo(Util.SQL_Begin);
			try
			{
				bool bSuccess = true;
				System.Version installedVersion = Package.InstalledVersion;
				if (installedVersion == new Version(0, 0, 0))
				{
					if (InstallScript != null)
					{
						bSuccess = InstallScriptFile(InstallScript);
						installedVersion = InstallScript.Version;
					}
				}
				if (bSuccess)
				{
					foreach (InstallFile file in InstallScripts.Values)
					{
						if (file.Version > installedVersion)
						{
							bSuccess = InstallScriptFile(file);
							if (!bSuccess)
							{
								break;
							}
						}
					}
				}
				if (UpgradeScript != null)
				{
					bSuccess = InstallScriptFile(UpgradeScript);
					installedVersion = UpgradeScript.Version;
				}
				if (bSuccess)
				{
					foreach (InstallFile file in UnInstallScripts.Values)
					{
						bSuccess = InstallFile(file);
						if (!bSuccess)
						{
							break;
						}
					}
				}
				Completed = bSuccess;
			}
			catch (Exception ex)
			{
				Log.AddFailure(ex);
			}
			Log.AddInfo(Util.SQL_End);
		}
		public override void Rollback()
		{
			base.Rollback();
		}
		public override void UnInstall()
		{
			Log.AddInfo(Util.SQL_BeginUnInstall);
			base.UnInstall();
			Log.AddInfo(Util.SQL_EndUnInstall);
		}
	}
}
